from __future__ import print_function

import ctypes
from ctypes import c_int

from llvmlite import ir

LLVM_INT_TYPE = ir.IntType(32)
LLVM_FLOAT_TYPE = ir.DoubleType()
LLVM_CHAR_TYPE = ir.IntType(8)
LLVM_STR_TYPE = ir.PointerType(LLVM_CHAR_TYPE)
LLVM_BOOL_TYPE = ir.IntType(1)
LLVM_NULL_TYPE = ir.VoidType
LLVM_LIST_CONTAINER_TYPE = ir.ArrayType


def get_llvm_list_full_type(elem_type):
    return ir.LiteralStructType([LLVM_INT_TYPE, elem_type.as_pointer()])


def is_llvm_list_type(ir_type):
    if isinstance(ir_type, ir.LiteralStructType):
        return (
            len(ir_type.elements) == 2
            and ir_type.elements[0] == LLVM_INT_TYPE
            and isinstance(ir_type.elements[1], ir.PointerType)
        )
    else:
        return False


def extract_llvm_list_elem_type(list_type: ir.LiteralStructType):
    return list_type.elements[1].pointee


def clist_type_factory(c_elem_type):
    class DynamicListType(ctypes.Structure):
        _fields_ = [("count", c_int), ("elems", ctypes.POINTER(c_elem_type))]

    DynamicListType.__name__ = "DynamicListType"
    return DynamicListType
